package com.suke.czx.modules.wx.controller;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.suke.czx.common.utils.CHttpRequest;
import com.suke.czx.common.utils.DateUtils;
import com.suke.czx.common.utils.JsonResult;
import com.suke.czx.common.utils.Query;
import com.suke.czx.modules.wx.util.MyX509TrustManager;
import com.suke.czx.modules.wxadmin.entity.DkReadPlanMsgEntity;
import com.suke.czx.modules.wxadmin.entity.DkUserEntity;
import com.suke.czx.modules.wxadmin.service.DkMsgContentService;
import com.suke.czx.modules.wxadmin.service.DkReadPlanMsgService;
import com.suke.czx.modules.wxadmin.service.DkUserService;

import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialFileBatchGetResult;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import net.sf.json.JSONObject;
import com.suke.czx.modules.wx.config.WxMpConfiguration;
import com.suke.czx.modules.wx.config.WxPayProperties;

@RestController
@RequestMapping("/wx/send")
public class SendSteateContronller {

	private static final Logger logger = LoggerFactory.getLogger(SendSteateContronller.class);
	@Autowired 
	private WxPayProperties wxPayProperties;
	
	@Autowired
	private DkMsgContentService dkMsgContentService;


	@Autowired
	private DkUserService dkUserService;

	@Autowired
	DkReadPlanMsgService dkReadPlanMsgService;

	@RequestMapping("/planned")
	public String planned() {

		String dateStr = DateUtils.getDate(new Date(), 0);
		String startTime = DateUtils.getDate(new Date(), -210);
		// 1、执行清空消息表；
		dkReadPlanMsgService.deleteAll();
		logger.info("=========>执行定时任务处理发送消息数据-清理数据：" + dateStr);
		// 2、数据迁移
		Map<String,String> parms = new HashMap<String,String>();
		parms.put("readDate", dateStr);
		parms.put("startTime", startTime);
		
		dkReadPlanMsgService.planedSave(parms);
		logger.info("=========>执行定时任务处理发送消息数据-迁移数据：" + dateStr);
		return new JsonResult(200, "数据迁移成功，每天凌晨做准备，为发送消息时候减轻服务器负担").toJson();
	}

	@RequestMapping("/tagtoall")
	public String tagto() {
		List<DkUserEntity> list = dkUserService.tagtoall();
		List<String> openids = new ArrayList<String>();
		for (int i = 0; i < list.size(); i++) {
			openids.add(list.get(i).getOpenid());
			if (openids.size() == 50) {
				doTagUser(101L, openids);
				openids.clear();
			}
		}
		doTagUser(101L, openids);
		return new JsonResult(200, "用户数据打标成功！").toJson();
	}

	@RequestMapping("/tagtoallnopay")
	public String tagtoallnopay() {
		List<DkUserEntity> list = dkUserService.tagtoallnopay();
		List<String> openids = new ArrayList<String>();
		for (int i = 0; i < list.size(); i++) {
			openids.add(list.get(i).getOpenid());
			if (openids.size() == 50) {
				doTagUser(102L, openids);
				openids.clear();
			}
		}
		doTagUser(102L, openids);
		return new JsonResult(200, "用户数据打标成功！").toJson();
	}

	public void doTagUser(Long tagId, List<String> openids) {
		JsonObject json = new JsonObject();
		json.addProperty("tagid", tagId);
		JsonArray openidArrayJson = new JsonArray();

		for (String openid : openids) {
			openidArrayJson.add(openid);
		}
		json.add("openid_list", openidArrayJson);
		String token = "";
		try {
			JSONObject obj = CHttpRequest.httpRequest("http://dk2019.hbanbao.com/x_springboot/wx/send/token/zhangdewen",
					"GET");
			token = obj.getString("data");
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			String url = "https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token=" + token;
			String result = myhttpsRequest(url, "POST", json.toString());
			logger.info("=========>用户打标成功！：" + result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@RequestMapping("/token/zhangdewen")
	public String token(){
		WxMpService wxMpService = WxMpConfiguration.getMpServices().get(wxPayProperties.getAppId());
		String token;
		try {
			token = wxMpService.getAccessToken();
			return new JsonResult(200,"ok",token).toJson();
		} catch (WxErrorException e) {
			e.printStackTrace();
			return new JsonResult(-1,e.getMessage()).toJson();
		}
	}
	
	@RequestMapping("/material/zhangdewen")
	public String material(String type,int offset ,int count){
		WxMpService wxMpService = WxMpConfiguration.getMpServices().get(wxPayProperties.getAppId());
		try {
			WxMpMaterialFileBatchGetResult materialFileBatchGet = wxMpService.getMaterialService().materialFileBatchGet(type, offset, count);
			return new JsonResult(200,"ok",materialFileBatchGet).toJson();
			
		} catch (WxErrorException e) {
			e.printStackTrace();
			return new JsonResult(-1,e.getMessage()).toJson();
		}
	}

	@RequestMapping("/msg/zhangdewen/20190322")
	public String send() {
		int limit = 2000;
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("sendState", 0);
		params.put("page", 1);
		params.put("limit", limit);
		// 查询列表数据
		Query query = new Query(params);
		Integer i = 0;
		while(true){
			List<Object> id = new ArrayList<Object>();
			List<DkReadPlanMsgEntity> list = dkReadPlanMsgService.queryList(query);
			// 判断今日是否还有相关数据要发送，如果没有就返回
			if (list == null || list.size() == 0) {
				logger.info("=========>消息全部发送成功！");
				return new JsonResult(200, "数据已经没有啦-定时任务发送用户消息成功！").toJson();
			}
			// =======================B
			
			for (DkReadPlanMsgEntity plan : list) {
				
				id.add(plan.getId());
			}
			// =======================E
			dkReadPlanMsgService.updateSendStateBatch(id.toArray());
			logger.info("=========>执行定时任务处理发送消息数据-发送数据：" + "第" + i + "波");
			WxMpService wxMpService = WxMpConfiguration.getMpServices().get(wxPayProperties.getAppId());
			Integer j = i;
			new Thread(new Runnable() {
				public void run() {
					int count=0;
					for (DkReadPlanMsgEntity plan : list) {
//						if(plan.getResourceId()>=45){
//							if(k%3==0){
//								continue;
//							}
//							k++;
//						}
						try {
							DkUserEntity user = dkUserService.queryObject(plan.getUserId(),true);
							sendMsgToUser(user, wxMpService.getAccessToken(),count+j*3000);
							count++;
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}).start();
			if(list.size()<limit){
				return new JsonResult(200, "数据已经没有啦-定时任务发送用户消息成功！").toJson();
			}
			i++;
			try {
				Thread.sleep(1500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}



	@RequestMapping("/msg/{openid}")
	public String sendByOpenid(@PathVariable String openid) {
		DkUserEntity user = dkUserService.queryObject(openid,true);
		WxMpService wxMpService = WxMpConfiguration.getMpServices().get(wxPayProperties.getAppId());
		int i=0;
		try {
			i = sendMsgToUser(user, wxMpService.getAccessToken(),0);
		} catch (WxErrorException e) {
			e.printStackTrace();
		}
		return new JsonResult(200, "ok" + i).toJson();
	}


	@RequestMapping("/tmp/{openid}")
	public String sendTmpByOpenid(@PathVariable String openid) {
		Random ra = new Random();
		DkUserEntity user = dkUserService.queryObject(openid,true);

		// 发送模板消息
		WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder().toUser(user.getOpenid())
				.templateId(wxPayProperties.getTidClassReminder()).build();
		templateMessage.addData(new WxMpTemplateData("first",
				user.getNickname() + ",今日课程内容已更新,已有7" + ra.nextInt(10) + "%同学完成今日学习\r\n\r\n", "#000000"));
		templateMessage.addData(new WxMpTemplateData("keyword1", "《210天学习计划》", "#000000"));
		templateMessage.addData(new WxMpTemplateData("keyword2", "学习时长约10分钟\r\n\r\n", "#000000"));
		templateMessage
				.addData(new WxMpTemplateData("remark", "点击下方【今日阅读】，完成今日的学习，每天坚持一点点，做更好的自己！\r\n\r\n↓↓↓", "#000000"));
		WxMpService wxMpService = WxMpConfiguration.getMpServices().get(wxPayProperties.getAppId());
		try {
			sendTemplateMsg(wxMpService.getAccessToken(), templateMessage);
		} catch (WxErrorException e) {
			e.printStackTrace();
		}
		return new JsonResult(200, "ok").toJson();
	}

	public int sendMsgToUser(DkUserEntity user, String token,int count) {
			
		String textContent = dkMsgContentService.queryObject(1).getContent();
		
		try {
			Random ra = new Random();
			WxMpKefuMessage message = WxMpKefuMessage.TEXT().toUser(user.getOpenid())
					.content(textContent.replace("{0}", user.getNickname()).replace("{1}", "7" + ra.nextInt(10))).build();
			
			if (!sendKefuMessage(token, message, count)) {
				// 发送模板消息
				WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder().toUser(user.getOpenid())
						.templateId(wxPayProperties.getTidClassReminder()).build();
				templateMessage.addData(new WxMpTemplateData("first",
						user.getNickname() + ",今日课程内容已更新,已有7" + ra.nextInt(10) + "%同学完成今日学习\r\n\r\n", "#000000"));
				templateMessage.addData(new WxMpTemplateData("keyword1", "《210天学习计划》", "#000000"));
				templateMessage.addData(new WxMpTemplateData("keyword2", "学习时长约10分钟\r\n\r\n", "#000000"));
				templateMessage.addData(
						new WxMpTemplateData("remark", "点击下方【今日阅读】，完成今日的学习，每天坚持一点点，做更好的自己！\r\n\r\n↓↓↓", "#000000"));
				sendTemplateMsg(token, templateMessage);
				return 1;
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("=======> 用户信息发送异常"  + user.getOpenid() + " " + e.getMessage());
		}
		return 0;
	}


	private void sendTemplateMsg(String token, WxMpTemplateMessage templateMessage) {
		String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + token;
		String result = myhttpsRequest(url, "POST", templateMessage.toJson());
		
		logger.info("=======> 模板消息發送結果："+templateMessage.getToUser() +" : " + result);
	}

	private boolean sendKefuMessage(String token, WxMpKefuMessage message,int count) {

		String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + token;
		String result = myhttpsRequest(url, "POST", message.toJson());
		logger.info("=======> 客服消息發送內容"+count+"："+message.getToUser() +" : " + result);

		JSONObject resultJson = JSONObject.fromObject(result);
		int errorCode = resultJson.getInt("errcode");
		String errMsg = resultJson.getString("errmsg");

		return StringUtils.equalsIgnoreCase(errMsg, "ok") && errorCode == 0;

	}

	public static String myhttpsRequest(String requestUrl, String requestMethod, String outputStr) {
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			conn.setRequestMethod(requestMethod);
			conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
			// 当outputStr不为null时向输出流写数据
			if (null != outputStr) {
				OutputStream outputStream = conn.getOutputStream();
				// 注意编码格式
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			// 从输入流读取返回内容
			InputStream inputStream = conn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String str = null;
			StringBuffer buffer = new StringBuffer();
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			// 释放资源
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			inputStream = null;
			conn.disconnect();
			return buffer.toString();
		} catch (ConnectException ce) {
			ce.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}


